package com.mbengue.corp.artisan.dao.impl;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;

import com.mbengue.corp.artisan.dao.ArticleFeuilleDao;
import com.mbengue.corp.artisan.modele.Article;
import com.mbengue.corp.artisan.modele.ArticlesFeuille;
import com.mbengue.corp.artisan.modele.Devis;
import com.mbengue.corp.artisan.modele.Facture;
import com.mbengue.corp.artisan.modele.Feuille;
import com.mbengue.corp.artisan.utils.TypeComposant;

public class ArticleFeuilleDaoImpl implements ArticleFeuilleDao {
  private static Logger logger = Logger.getLogger(ArticleFeuilleDao.class);
  private HibernateTemplate hbTemplate;

  public void setSessionFactory(SessionFactory sessionFactory) {
    this.hbTemplate = new HibernateTemplate(sessionFactory);
  }

  @Override
  public void ajouterArticleFeuille(ArticlesFeuille articlesFeuille) throws DataAccessException {
    logger.info("Assignation d'un article a une feuille: " + articlesFeuille);
    this.hbTemplate.saveOrUpdate(articlesFeuille);
  }

  @Override
  public void modifierArticleFeuille(ArticlesFeuille articlesFeuille) throws DataAccessException {
    logger.info("Mise a jour de l'articleFeuille: " + articlesFeuille);
    this.hbTemplate.update(articlesFeuille);
  }

  @Override
  public void supprimerArticleFeuille(ArticlesFeuille articlesFeuille) throws DataAccessException {
    logger.info("ArticlesFeuille a supprimer: " + articlesFeuille);
    this.hbTemplate.delete(articlesFeuille);
  }

  @SuppressWarnings("unchecked")
  @Override
  public ArticlesFeuille trouverArticleFeuille(Feuille feuille, Article article) throws DataAccessException {
    logger.info("Trouve la jointure entre la feuille n° " + feuille.getNumero() + " et l'article n° "
        + article.getCode());
    DetachedCriteria criteria = DetachedCriteria.forClass(ArticlesFeuille.class);
    criteria.add(Restrictions.and(Restrictions.eq("feuille", feuille), Restrictions.eq("article", article)));
    List<ArticlesFeuille> articlesFeuilles = this.hbTemplate.findByCriteria(criteria);
    Assert.isTrue(articlesFeuilles.size() <= 1);

    if (articlesFeuilles.isEmpty()) {
      return null;
    }
    return articlesFeuilles.get(0);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<Article> tousLesArticlesD1Feuille(String numero) throws DataAccessException {
    logger.info("Trouve tous les articles de la feuille n° " + numero);
    return this.hbTemplate.findByNamedQuery("tousLesArticlesD1Feuille", numero);
  }

  @Override
  public List<Article> tousLesArticlesD1Facture(String numero) throws DataAccessException {
    return this.tousLesArticlesD1Feuille(numero);
  }

  @Override
  public List<Article> tousLesArticlesD1Devis(String numero) throws DataAccessException {
    return this.tousLesArticlesD1Feuille(numero);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<Feuille> toutesLesFeuillesD1Article(Article article) throws DataAccessException {
    logger.info("Trouve toutes les feuilles contenant cet article: " + article.getCode());
    return this.hbTemplate.findByNamedQuery("toutesLesFeuillesD1Article", article.getCode());
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<Facture> toutesLesFacturesD1Article(Article article) throws DataAccessException {
    logger.info("Trouve toutes les factures contenant cet article: " + article.getCode());
    return this.hbTemplate.findByNamedQuery("toutesLesFeuillesD1ArticleParType",
        new String[] { TypeComposant.FACTURE.getNom(), article.getCode() });
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<Devis> tousLesDevisD1Article(Article article) throws DataAccessException {
    logger.info("Trouve tous les devis contenant cet article: " + article.getCode());
    return this.hbTemplate.findByNamedQuery("toutesLesFeuillesD1ArticleParType",
        new String[] { TypeComposant.DEVIS.getNom(), article.getCode() });
  }

  @SuppressWarnings("unchecked")
  @Override
  public void supprimerJointureParFeuille(Feuille feuille) throws DataAccessException {
    logger
        .info("Suppression de toutes les jointures sur lesquelles cette facture est presente: " + feuille.getNumero());
    List<ArticlesFeuille> artFeus = this.hbTemplate.find("select af from ArticlesFeuille af where af.feuille = ?",
        feuille);
    this.hbTemplate.deleteAll(artFeus);
  }

  @SuppressWarnings("unchecked")
  @Override
  public void supprimerJointureParArticle(Article article) throws DataAccessException {
    logger.info("Suppression de toutes les jointures sur lesquelles cet article est present: " + article.getCode());
    List<ArticlesFeuille> artFeus = this.hbTemplate.find("select af from ArticlesFeuille af where af.article = ?",
        article);
    this.hbTemplate.deleteAll(artFeus);
  }
}
